/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.logiclander.ricemine.services.identity;

import com.logiclander.ricemine.utils.LdapUtilities;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.kuali.rice.kim.bo.entity.dto.KimEntityAffiliationInfo;
import org.kuali.rice.kim.bo.entity.dto.KimEntityBioDemographicsInfo;
import org.kuali.rice.kim.bo.entity.dto.KimEntityCitizenshipInfo;
import org.kuali.rice.kim.bo.entity.dto.KimEntityEmploymentInformationInfo;
import org.kuali.rice.kim.bo.entity.dto.KimEntityEntityTypeInfo;
import org.kuali.rice.kim.bo.entity.dto.KimEntityEthnicityInfo;
import org.kuali.rice.kim.bo.entity.dto.KimEntityExternalIdentifierInfo;
import org.kuali.rice.kim.bo.entity.dto.KimEntityInfo;
import org.kuali.rice.kim.bo.entity.dto.KimEntityNameInfo;
import org.kuali.rice.kim.bo.entity.dto.KimEntityPrivacyPreferencesInfo;
import org.kuali.rice.kim.bo.entity.dto.KimEntityResidencyInfo;
import org.kuali.rice.kim.bo.entity.dto.KimEntityVisaInfo;
import org.kuali.rice.kim.bo.entity.dto.KimPrincipalInfo;
import org.kuali.rice.kns.util.TypedArrayList;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;

/**
 *
 * @author tcarroll
 */
public class LdapKimEntityInfoMapper implements ContextMapper {

  private final Log log = LogFactory.getLog(getClass());
  private String entityIdAttributeName = null;
  private LdapKimPrincipalInfoMapper ldapKimPrincipalInfoMapper = null;
  private LdapKimEntityNameInfoMapper ldapKimEntityNameInfoMapper = null;
  private LdapKimEntityEntityTypeInfoMapper ldapKimEntityEntityTypeInfoMapper = null;
  private LdapKimEntityExternalIdentifierInfoMapper ldapKimEntityExternalIdentifierInfoMapper = null;
  private LdapKimEntityAffiliationsInfoMapper ldapKimEntityAffiliationsInfoMapper = null;
  private LdapKimEntityEmploymentInformationInfoMapper ldapKimEntityEmploymentInformationInfoMapper = null;
  private LdapKimEntityPrivacyPreferencesInfoMapper ldapKimEntityPrivacyPreferencesInfoMapper = null;
  private LdapKimEntityBioDemographicsInfoMapper ldapKimEntityBioDemographicsInfoMapper = null;
  private LdapKimEntityCitizenshipInfoMapper ldapKimEntityCitizenshipInfoMapper = null;
  private LdapKimEntityEthnicityInfoMapper ldapKimEntityEthnicityInfoMapper = null;
  private LdapKimEntityResidencyInfoMapper ldapKimEntityResidencyInfoMapper = null;
  private LdapKimEntityVisaInfoMapper ldapKimEntityVisaInfoMapper = null;

//beg: methods required by ContextMapper interface
  public Object mapFromContext(Object ctx) {
    validateConfiguration();
    KimEntityInfo kei = new KimEntityInfo();
    try {
      DirContextAdapter context = (DirContextAdapter) ctx;
//map entityId
      // potential to be special or synthetic, so do some special processing
      if (context.getStringAttribute(entityIdAttributeName).equalsIgnoreCase("dn")) {
        kei.setEntityId(LdapUtilities.buildDn(context, true));
      } else if (context.getStringAttribute(entityIdAttributeName).equals("objectGUID")) {
        kei.setEntityId(LdapUtilities.buildGuid(context));
      } else {
        kei.setEntityId(context.getStringAttribute(entityIdAttributeName));
      }
//map principals
      List<KimPrincipalInfo> kpis = new TypedArrayList(KimPrincipalInfo.class);
      kpis.add((KimPrincipalInfo) ldapKimPrincipalInfoMapper.mapFromContext(ctx));
      kei.setPrincipals(kpis);
//map names
      List<KimEntityNameInfo> kenis = new TypedArrayList(KimEntityNameInfo.class);
      kenis.add((KimEntityNameInfo) ldapKimEntityNameInfoMapper.mapFromContext(ctx));
      kei.setNames(kenis);
//rice team removed setDefaultName method and changed the getDefaultName method
//          to derive default, so for those newer versions (> 1.0.1.1) the following line.
//          so what to do.... hmmm... wish there was a deprication instead.
// only need this for < 1.0.2      kei.setDefaultName((KimEntityNameInfo) LdapUtilities.getKimDefaultItem(kenis));
//map entityTypes
      List<KimEntityEntityTypeInfo> keetis = new TypedArrayList(KimEntityEntityTypeInfo.class);
      keetis.add((KimEntityEntityTypeInfo) ldapKimEntityEntityTypeInfoMapper.mapFromContext(ctx));
      kei.setEntityTypes(keetis);
//map externalIdentifiers
      List<KimEntityExternalIdentifierInfo> keeidi = new TypedArrayList(KimEntityExternalIdentifierInfo.class);
      keeidi.add((KimEntityExternalIdentifierInfo) ldapKimEntityExternalIdentifierInfoMapper.mapFromContext(ctx));
      kei.setExternalIdentifiers(keeidi);
//map affiliations
//      List<KimEntityAffiliationInfo> keai = new TypedArrayList(KimEntityAffiliationInfo.class);
//      keai.add((KimEntityAffiliationInfo) ldapKimEntityAffiliationsInfoMapper.mapFromContext(ctx));
//      kei.setAffiliations(keai);
      kei.setAffiliations(ldapKimEntityAffiliationsInfoMapper.mapFromContext(ctx));
//rice team removed setDefaultAffiliation method and changed the getDefaultAffiliation method
//          to derive default, so for those newer versions (> 1.0.1.1) the following line.
//          so what to do.... hmmm... wish there was a deprication instead.
// only need this for < 1.0.2      kei.setDefaultAffiliation((KimEntityAffiliationInfo) LdapUtilities.getKimDefaultItem(keai));
//map employmentInformation
      List<KimEntityEmploymentInformationInfo> keeii = new TypedArrayList(KimEntityEmploymentInformationInfo.class);
      keeii.add((KimEntityEmploymentInformationInfo) ldapKimEntityEmploymentInformationInfoMapper.mapFromContext(ctx));
      kei.setEmploymentInformation(keeii);
//rice team removed setPrimaryEmployment method and changed the getPrimaryEmloyment method
//          to derive default, so for those newer versions (> 1.0.1.1) the following line.
//          so what to do.... hmmm... wish there was a deprication instead.
// only need this for < 1.0.2      kei.setPrimaryEmployment(getPrimaryEmployment(keeii));
//map privacyPreferences
      KimEntityPrivacyPreferencesInfo keppi = (KimEntityPrivacyPreferencesInfo) ldapKimEntityPrivacyPreferencesInfoMapper.mapFromContext(ctx);
      kei.setPrivacyPreferences(keppi);
//map bioDemographics
      KimEntityBioDemographicsInfo kebdi = (KimEntityBioDemographicsInfo) ldapKimEntityBioDemographicsInfoMapper.mapFromContext(ctx);
      kei.setBioDemographics(kebdi);
//map citizenships
      List<KimEntityCitizenshipInfo> keci = new TypedArrayList(KimEntityCitizenshipInfo.class);
      keci.add((KimEntityCitizenshipInfo) ldapKimEntityCitizenshipInfoMapper.mapFromContext(ctx));
      kei.setCitizenships(keci);
//map ethnicities
      List<KimEntityEthnicityInfo> keei = new TypedArrayList(KimEntityEthnicityInfo.class);
      keei.add((KimEntityEthnicityInfo) ldapKimEntityEthnicityInfoMapper.mapFromContext(ctx));
      kei.setEthnicities(keei);
//map residencies
      List<KimEntityResidencyInfo> keri = new TypedArrayList(KimEntityResidencyInfo.class);
      keri.add((KimEntityResidencyInfo) ldapKimEntityResidencyInfoMapper.mapFromContext(ctx));
      kei.setResidencies(keri);
//map visas
      List<KimEntityVisaInfo> kevi = new TypedArrayList(KimEntityVisaInfo.class);
      kevi.add((KimEntityVisaInfo) ldapKimEntityVisaInfoMapper.mapFromContext(ctx));
      kei.setVisas(kevi);

//todo: determine how to apply this if necessary
//  public KimEntityEntityType getEntityType(String entityTypeCode) {
//    for (KimEntityEntityTypeInfo entType : entityTypes) {
//      if (entType.getEntityTypeCode().equals(entityTypeCode)) {
//        return entType;
//      }
//    }
//    return null;
//  }
//
//todo: determine how to apply this if necessary
//  public KimEntityEmploymentInformation getPrimaryEmployment() {
//    for (KimEntityEmploymentInformationInfo emp : employmentInformation) {
//      if (emp.isActive() && emp.isPrimary()) {
//        return emp;
//      }
//    }
//    return null;
//  }
//
      kei.setActive(true);

    } catch (Throwable t) {
      log.error("Error in ContextMapper", t);
      String msg = "ContextMapper failed to create a LdapRecord from the specified Context: " + ctx;
      throw new RuntimeException(msg, t);
    }
    if (log.isDebugEnabled()) {
      log.debug("mapped entity: entityId=" + kei.getEntityId()
              + ", isActive=" + kei.isActive());
    }
    return kei;
  }
//end: methods required by ContextMapper interface
//beg: configuration methods

  public String getEntityIdAttributeName() {
    return this.entityIdAttributeName;
  }

  public void setEntityIdAttributeName(String attrName) {
    this.entityIdAttributeName = attrName;
  }

  public LdapKimPrincipalInfoMapper getLdapKimPrincipalInfoMapper() {
    return this.ldapKimPrincipalInfoMapper;
  }

  public void setLdapKimPrincipalInfoMapper(LdapKimPrincipalInfoMapper ldapKimPrincipalInfoMapper) {
    this.ldapKimPrincipalInfoMapper = ldapKimPrincipalInfoMapper;
  }

  public LdapKimEntityNameInfoMapper getLdapKimEntityNameInfoMapper() {
    return this.ldapKimEntityNameInfoMapper;
  }

  public void setLdapKimEntityNameInfoMapper(LdapKimEntityNameInfoMapper ldapKimEntityNameInfoMapper) {
    this.ldapKimEntityNameInfoMapper = ldapKimEntityNameInfoMapper;
  }

  public LdapKimEntityEntityTypeInfoMapper getLdapKimEntityEntityTypeInfoMapper() {
    return this.ldapKimEntityEntityTypeInfoMapper;
  }

  public void setLdapKimEntityEntityTypeInfoMapper(LdapKimEntityEntityTypeInfoMapper ldapKimEntityEntityTypeInfoMapper) {
    this.ldapKimEntityEntityTypeInfoMapper = ldapKimEntityEntityTypeInfoMapper;
  }

  public LdapKimEntityExternalIdentifierInfoMapper getLdapKimEntityExternalIdentifierInfoMapper() {
    return this.ldapKimEntityExternalIdentifierInfoMapper;
  }

  public void setLdapKimEntityExternalIdentifierInfoMapper(LdapKimEntityExternalIdentifierInfoMapper ldapKimEntityExternalIdentifierInfoMapper) {
    this.ldapKimEntityExternalIdentifierInfoMapper = ldapKimEntityExternalIdentifierInfoMapper;
  }

  public LdapKimEntityAffiliationsInfoMapper getLdapKimEntityAffiliationsInfoMapper() {
    return this.ldapKimEntityAffiliationsInfoMapper;
  }

  public void setLdapKimEntityAffiliationsInfoMapper(LdapKimEntityAffiliationsInfoMapper ldapKimEntityAffiliationsInfoMapper) {
    this.ldapKimEntityAffiliationsInfoMapper = ldapKimEntityAffiliationsInfoMapper;
  }

  public LdapKimEntityEmploymentInformationInfoMapper getLdapKimEntityEmploymentInformationInfoMapper() {
    return this.ldapKimEntityEmploymentInformationInfoMapper;
  }

  public void setLdapKimEntityEmploymentInformationInfoMapper(LdapKimEntityEmploymentInformationInfoMapper ldapKimEntityEmploymentInformationInfoMapper) {
    this.ldapKimEntityEmploymentInformationInfoMapper = ldapKimEntityEmploymentInformationInfoMapper;
  }

  public LdapKimEntityPrivacyPreferencesInfoMapper getLdapKimEntityPrivacyPreferencesInfoMapper() {
    return this.ldapKimEntityPrivacyPreferencesInfoMapper;
  }

  public void setLdapKimEntityPrivacyPreferencesInfoMapper(LdapKimEntityPrivacyPreferencesInfoMapper ldapKimEntityPrivacyPreferencesInfoMapper) {
    this.ldapKimEntityPrivacyPreferencesInfoMapper = ldapKimEntityPrivacyPreferencesInfoMapper;
  }

  public LdapKimEntityBioDemographicsInfoMapper getLdapKimEntityBioDemographicsInfoMapper() {
    return this.ldapKimEntityBioDemographicsInfoMapper;
  }

  public void setLdapKimEntityBioDemographicsInfoMapper(LdapKimEntityBioDemographicsInfoMapper ldapKimEntityBioDemographicsInfoMapper) {
    this.ldapKimEntityBioDemographicsInfoMapper = ldapKimEntityBioDemographicsInfoMapper;
  }

  public LdapKimEntityCitizenshipInfoMapper getLdapKimEntityCitizenshipInfoMapper() {
    return this.ldapKimEntityCitizenshipInfoMapper;
  }

  public void setLdapKimEntityCitizenshipInfoMapper(LdapKimEntityCitizenshipInfoMapper ldapKimEntityCitizenshipInfoMapper) {
    this.ldapKimEntityCitizenshipInfoMapper = ldapKimEntityCitizenshipInfoMapper;
  }

  public LdapKimEntityEthnicityInfoMapper getLdapKimEntityEthnicityInfoMapper() {
    return this.ldapKimEntityEthnicityInfoMapper;
  }

  public void setLdapKimEntityEthnicityInfoMapper(LdapKimEntityEthnicityInfoMapper ldapKimEntityEthnicityInfoMapper) {
    this.ldapKimEntityEthnicityInfoMapper = ldapKimEntityEthnicityInfoMapper;
  }

  public LdapKimEntityResidencyInfoMapper getLdapKimEntityResidencyInfoMapper() {
    return this.ldapKimEntityResidencyInfoMapper;
  }

  public void setLdapKimEntityResidencyInfoMapper(LdapKimEntityResidencyInfoMapper ldapKimEntityResidencyInfoMapper) {
    this.ldapKimEntityResidencyInfoMapper = ldapKimEntityResidencyInfoMapper;
  }

  public void setLdapKimEntityVisaInfoMapper(LdapKimEntityVisaInfoMapper ldapKimEntityVisaInfoMapper) {
    this.ldapKimEntityVisaInfoMapper = ldapKimEntityVisaInfoMapper;
  }

  private void validateConfiguration() {
    if (entityIdAttributeName == null) {
      String msg = "The property 'entityIdAttributeName' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimPrincipalInfoMapper == null) {
      String msg = "The property 'ldapKimPrincipalInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityNameInfoMapper == null) {
      String msg = "The property 'ldapKimEntityNameInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityEntityTypeInfoMapper == null) {
      String msg = "The property 'ldapKimEntityEntityTypeInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityExternalIdentifierInfoMapper == null) {
      String msg = "The property 'ldapKimEntityExternalIdentifierInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityAffiliationsInfoMapper == null) {
      String msg = "The property 'ldapKimEntityAffiliationInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityEmploymentInformationInfoMapper == null) {
      String msg = "The property 'ldapKimEntityEmploymentInformationInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityEmploymentInformationInfoMapper == null) {
      String msg = "The property 'ldapKimEntityEmploymentInformationInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityPrivacyPreferencesInfoMapper == null) {
      String msg = "The property 'ldapKimEntityPrivacyPreferencesInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityBioDemographicsInfoMapper == null) {
      String msg = "The property 'ldapKimEntityBioDemographicsInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityCitizenshipInfoMapper == null) {
      String msg = "The property 'ldapKimEntityCitizenshipInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityEthnicityInfoMapper == null) {
      String msg = "The property 'ldapKimEntityEthnicityInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityResidencyInfoMapper == null) {
      String msg = "The property 'ldapKimEntityResidencyInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
    if (ldapKimEntityVisaInfoMapper == null) {
      String msg = "The property 'ldapKimEntityVisaInfoMapper' must be set.";
      throw new IllegalStateException(msg);
    }
  }
//end: configuration methods
//beg: helper methods

  protected KimEntityEmploymentInformationInfo getPrimaryEmployment(List<KimEntityEmploymentInformationInfo> list) {
    // find the default entry
    for (KimEntityEmploymentInformationInfo item : list) {
      if (item.isPrimary() && item.isActive()) {
        return item;
      }
    }
    // if no default, return the first
    if (list.size() > 0) {
      return list.get(0);
    }
    // if neither, return null
    return null;
  }
//end: helper methods
}


